package gtgold;

import javax.imageio.ImageIO;
import javax.swing.*;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.List;
import java.util.*;
import java.util.Map.Entry;

/**
 * Manages flow of the game
 * 
 * @author Robert, jo
 */
public class GameManager
{
	// Accessibility can always be changed later if necessary
	public final GameData data;
	MainScreen mainScreen;
	RandomEvents randomEvents = new RandomEvents(this);

	/**
	 * Start a new game with specified job and party member names. Parameters
	 * for other starting options may be added later. Throws
	 * IllegalArgumentException for invalid arguments
	 * 
	 * @param job
	 * @param names
	 *            Empty strings and nulls are treated as nonexistent party
	 *            members. There should be at least one valid name. Names in
	 *            excess of five will be ignored.
	 */
	public GameManager(Occupation job, List<String> names)
	{
		// Filter names
		List<String> nameList = new ArrayList<String>();
		for (String s : names)
		{
			if (s != null && s.length() > 0)
			{
				nameList.add(s);
			}
		}

		// Verify inputs
		if (nameList.isEmpty())
		{
			throw new IllegalArgumentException("Please enter a valid name");
		}

		if (job == null)
		{
			throw new IllegalArgumentException(
					"Please enter a valid occupation");
		}

		// Create Game Data
		data = new GameData(this, job, nameList);

		// Ready game data to be saved
		OregonTrail.menuBar.data = data;
		
		mainScreen = new MainScreen(this);
		OregonTrail.mainScreen(mainScreen);

		// Start shopping!
		openShopMenu();
	}

	/**
	 * Re-construct game objects from a loaded file
	 * 
	 * @param data
	 */
	public GameManager(GameData data)
	{
		this.data = data;
		data.manager = this;
		
		mainScreen = new MainScreen(this);
		OregonTrail.mainScreen(mainScreen);
	}
	
	public void update()
	{
		boolean moved = data.update();
		randomEvents.doEvents(data, moved);
	}

	/**
	 * Alert the user with an informational pop-up dialog
	 * 
	 * @param text to display
	 */
	public void openInfoDialog(String text)
	{
		JOptionPane.showMessageDialog(OregonTrail.frame, text, "Info",
				JOptionPane.INFORMATION_MESSAGE);
	}

	/**
	 * Ask the user with a YES/NO dialog
	 * 
	 * @param text to display
	 * @return true if yes selected, false if no
	 */
	public boolean openYesNoDialog(String text)
	{
		return JOptionPane.showConfirmDialog(OregonTrail.frame, text,
				"Question", JOptionPane.YES_NO_OPTION) == 0 ? true : false;
	}

	/**
	 * Opens a modal dialog box with a button for each value in the options Map
	 * 
	 * @param text
	 *            String text to display above buttons
	 * @param options
	 *            Map return value to button text
	 * @param allowCancel
	 *            boolean to include a cancel button
	 * @return mapped result of button pushed OR NULL if dialog closed / cancel
	 *         pressed
	 */
	@SuppressWarnings("unchecked")
	public <T> T openOptionDialog(String text, Map<T, String> options,
			boolean allowCancel)
	{
		GenericOptionDialog dialog = new GenericOptionDialog(text, options,
				allowCancel);
		return (T) dialog.showDialog();
	}

	/**
	 * Open a new shop modal dialog box where the party can purchase supplies
	 */
	public void openShopMenu()
	{
		if (!data.Location().isShop())
		{
			openInfoDialog("You are not at a store and hence, cannot go shopping.");
		} else
		{
			Location loc = data.Location();
			new Shopping(this, loc.name + " General Store", loc.prices);
		}
	}

	/**
	 * Open the 'Other Options' dialog
	 * where additional party information
	 * can be viewed / edited
	 */
	public void openInventory()
	{
		new InventoryMenu(this);
	}

	/**
	 * Open the 'Drop Junk' dialog
	 * where supplies can be jettisoned
	 */
	public void openDropMenu()
	{
		new DropMenu();
	}

	private class DropMenu extends JDialog
	{
		private static final long serialVersionUID = 1L;
		private EnumMap<Item, JTextField> quantityFields;

		public DropMenu()
		{
			super(OregonTrail.frame, "Drop junk", true);

			setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
			setResizable(false);
			setPreferredSize(new Dimension(320, 400));

			setLayout(new GridLayout(10, 4));

			quantityFields = new EnumMap<Item, JTextField>(Item.class);

			// R1
			add(new JLabel("<html>&nbsp;&nbsp;<b>Item</b></html>"));
			add(new JLabel("<html><b>Unit weight</b></html>"));
			add(new JLabel("<html><b>Have</b></html>"));
			add(new JLabel("<html><b>Drop amount</b></html>"));

			// R2 - R9
			for (Item i : Item.values())
			{
				add(new JLabel("  " + i.toString()));
				add(new JLabel("" + (int) i.getWeight() + " lbs"));
				add(new JLabel("" + (int) data.inventory.get(i)));

				quantityFields.put(i, new JTextField());
				add(quantityFields.get(i));
			}

			// R10
			JPanel p1 = new JPanel();
			p1.add(new JLabel(
					"<html>&nbsp;&nbsp;<b>Current<br/>&nbsp;&nbsp;weight:</b></html>"));

			JPanel p2 = new JPanel();
			p2.add(new JLabel("<html><b><br/>" + (int) data.inventory.weight()
					+ " lbs</b></html>"));

			Color c = new Color(120, 240, 0);
			p1.setBackground(c);
			p2.setBackground(c);

			add(p1);
			add(p2);
			add(new JLabel());

			JButton dump = new JButton("Dump");
			dump.addActionListener(new DumpListener());

			add(dump);

			// JDialog initialization
			pack();
			setLocationRelativeTo(OregonTrail.frame);
			setVisible(true);
		}

		private class DumpListener implements ActionListener
		{
			public void actionPerformed(ActionEvent arg0)
			{
				for (Entry<Item, JTextField> e : quantityFields.entrySet())
				{
					int dropAmount = 0;
					double have = data.inventory.get(e.getKey());

					// OMG CHEAT CODE!!
					if (e.getValue().getText().equals("l33t"))
						data.inventory.set(e.getKey(), have += 1337);

					try
					{
						dropAmount = Integer.valueOf(e.getValue().getText());
					} catch (NumberFormatException nfe)
					{
					}

					if (dropAmount >= 0 && dropAmount <= have)
						data.inventory.set(e.getKey(), have - dropAmount);
				}

				dispose();
			}

		}
	}

	public class bgImagePanel extends JPanel
	{
		private static final long serialVersionUID = 1L;
		private BufferedImage background;

		/**
		 * Create the panel.
		 */
		public bgImagePanel(String filename)
		{
			try
			{
				background = ImageIO.read(new File(filename));
			} catch (IOException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			// setLayout(new GridLayout(3, 3, 2, 2));
			setLayout(new FlowLayout());
		}

		public void paintComponent(Graphics g)
		{
			super.paintComponent(g);
			g.drawImage(background, 0, 0, null);
		}
	}
}
